use crate::block::Block;

#[derive(Debug)]
pub struct PageArea {
    pub(crate) start: *mut u8,
    pub size: usize,
}

impl PageArea {
    pub fn new(start: *mut u8, size: usize) -> Self {
        PageArea { start, size }
    }

    pub fn contains_ptr(&self, ptr: *mut u8) -> bool {
        let start = self.start as usize;
        let end = start + self.size;
        let p = ptr as usize;
        p >= start && p < end
    }

    pub fn init_blocks(&mut self, block_size: usize) -> *mut Block {
        let total_block_size = block_size + std::mem::size_of::<Block>();
        let capacity = self.size / total_block_size;
        debug_log!("  ├─ Initializing blocks:");
        debug_log!("     ├─ Area size: {} bytes", self.size);
        debug_log!("     ├─ Total block size: {} bytes", total_block_size);
        debug_log!("     ├─ Theoretical capacity: {} blocks", capacity);
        debug_log!("     └─ Creating {} blocks", capacity);

        unsafe {
            let mut current = self.start;
            let mut first_block = std::ptr::null_mut();

            for i in 0..capacity {
                let block = Block::init(current, block_size);
                if i < capacity - 1 {
                    (*block).next = Block::init(current.add(total_block_size), block_size);
                }
                if i == 0 {
                    first_block = block;
                }
                current = current.add(total_block_size);
            }
            first_block
        }
    }
}

unsafe impl Send for PageArea {}
unsafe impl Sync for PageArea {}
